﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Clipping.Infrastructure.Models;
using System.Web;

namespace Clipping.Utils.SearchEngines
{
    public class ChinaDaily:ISearchEngine
    {

        private Encoding _urlEncoding = Encoding.UTF8;

        public void Parse(Uri url, string html, out List<News> news, out string nextPageUrl)
        {
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
        }

        public Uri ConstructUrl(SearchObject searchObj)
        {
            return constructUrl(searchObj);
        }

        public void Search(SearchObject searchObj, IHtmlDownload downloader, out List<News> news, out string nextPageUrl)
        {
            var url = constructUrl(searchObj);
            string html = downloader.GetHtml(url);
            parse(html, out news, out nextPageUrl);
            if (!string.IsNullOrEmpty(nextPageUrl))
                nextPageUrl = constructAbsoluteUrl(url, nextPageUrl).OriginalString;
        }


        #region 私有方法
        private Uri constructUrl(SearchObject searchObj)
        {
            if (searchObj is TimespanSearchObject)
            {
                TimespanSearchObject so = searchObj as TimespanSearchObject;

                return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), so.StartTime, so.EndTime));

            }
            else if (searchObj is PeriodSearchObject)
            {
                PeriodSearchObject so = searchObj as PeriodSearchObject;
                DateTime now = DateTime.Now;
                switch (so.SearchPeriod)
                {
                    case SearchPeriod.全部时间:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate=&strFromdate=&usedate=&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding)));
                    case SearchPeriod.最近1年:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddYears(-1), now));
                    case SearchPeriod.最近1天:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddDays(-1), now));
                    case SearchPeriod.最近1月:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddMonths(-1), now));
                    case SearchPeriod.最近1周:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddDays(-7), now));
                    case SearchPeriod.最近2天:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddDays(-2), now));
                    case SearchPeriod.最近2月:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddMonths(-2), now));
                    case SearchPeriod.最近3天:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddDays(-3), now));
                    case SearchPeriod.最近3月:
                        return new Uri(string.Format("http://search.chinadaily.com.cn/cn.jsp?searchText={0}&strTodate={2:yyyy-MM-dd}&strFromdate={1:yyyy-MM-dd}&usedate=yes&strAuthor=", HttpUtility.UrlEncode(searchObj.Keyword, this._urlEncoding), now.AddMonths(-3), now));
                    default:
                        return null;
                }

            }
            else
                return null;

        }

        private Uri constructAbsoluteUrl(Uri baseUri, string url)
        {
            var baseUrl = baseUri.OriginalString;
            if (Regex.Match(baseUrl, @"&page=\d+", RegexOptions.IgnoreCase).Success)
            {
                return new Uri(Regex.Replace(baseUrl, @"&page=\d+", "&page=" + url, RegexOptions.IgnoreCase));
            }
            else
            {
                return new Uri(string.Format("{0}&page={1}", baseUrl, url));
            }


        }

        private void parse(string html, out List<News> news, out string nextPageUrl)
        {
            news = new List<News>();
            nextPageUrl = null;
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(html);
            var liNav = doc.CreateNavigator();
            string h = ((HtmlAgilityPack.HtmlNodeNavigator)(liNav)).CurrentNode.OuterHtml;

            var divSearchResult = liNav.Select("//div[@class='topNews_a']");
            while (divSearchResult.MoveNext())
            {
                News n = new News();
                n.Media = "中国日报网";

                var li = divSearchResult.Current;

                //取标题和链接
                var linkNode = li.SelectSingleNode("descendant::a");
                if (linkNode != null)
                {
                    n.Title = n.Title = n.Title = System.Web.HttpUtility.HtmlDecode(linkNode.Value);

                    n.Url = System.Web.HttpUtility.UrlDecode(linkNode.GetAttribute("href", ""));
                }

                //取日期
                var str = li.Value;
                var titleStr = linkNode.Value;
                var dateStr = str.Replace(titleStr, "");
                var dateMatch = Regex.Match(dateStr, @"\d{4}-\d{2}-\d{2}");
                if (dateMatch.Success)
                    n.PubDate = dateMatch.Value;

                //取摘要
                var liHtml = ((HtmlAgilityPack.HtmlNodeNavigator)(li)).CurrentNode.OuterHtml;

                var startIndex = h.IndexOf(liHtml, StringComparison.OrdinalIgnoreCase) + liHtml.Length;
                var subStr = h.Substring(startIndex);
                var endIndex = subStr.IndexOf("<div", StringComparison.OrdinalIgnoreCase);
                n.Summary = subStr.Substring(0, endIndex);

                news.Add(n);
            }

            //取下一页地址
            var aList = liNav.Select("descendant::a");
            if (aList != null)
            {
                while (aList.MoveNext())
                {

                    var a = aList.Current;
                    string npu = a.GetAttribute("href", "");
                    if (a.Value != null && a.Value.Contains("下一页") && npu.Contains("javascript:gopage"))
                    {
                        nextPageUrl = Regex.Match(npu, @"javascript:gopage\((\d+)\)").Groups[1].Value;
                        break;
                    }
                }
            }
        }

        #endregion

     

        #region 属性
        public string Name
        {
            get { return "中国日报网"; }
        }
        public Encoding ContentEncoding
        {
            get { return _urlEncoding; }
        }
        #endregion


      
    }
}
